package cn.hongsw.monitor.task;

import lombok.Cleanup;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.springframework.boot.context.properties.ConfigurationProperties;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author :hongsw
 * @date :2021-10-11 11:31
 */
@ConfigurationProperties("file-monitor-and-push-ftp")
@Data
@Slf4j
public class FileMonitorAndPushFtpManagement {
    /**
     * 文件监控路径
     */
    private String fileMonitorPath;

    /**
     * 监控间隔
     */
    private Long monitorInterval;

    /**
     * 需要监控的文件类型
     */
    private List<String> needMonitorFile;

    /**
     * 推送ftp集群配置
     */
    private List<FtpConfig> ftpConfigs;

    /**
     * 微软操作系统
     */
    public static final String WINDOWS_OS = "windows";

    /**
     * LINUX操作系统
     */
    public static final String LINUX_OS = "linux";

    /**
     * 监控推送文件
     *
     * @author hongsw
     * @date 2021/10/13 16:18
     **/
    @PostConstruct
    public void monitor() throws Exception {
        FileAlterationMonitor monitor = new FileAlterationMonitor(monitorInterval);
        File monitorPath = new File(fileMonitorPath);
        if (!monitorPath.exists()) {
            log.error("文件夹路径不存在：{}", fileMonitorPath);
            return;
        }
        FileAlterationObserver observer = new FileAlterationObserver(monitorPath, new FileFilter(needMonitorFile));
        monitor.addObserver(observer);
        FtpFileAlterationListener ftpFileAlterationListener = new FtpFileAlterationListener() {
            @SneakyThrows
            @Override
            public void onFileCreate(File file) {
                String absolutePath = file.getAbsolutePath();
                String needMkdir = absolutePath.replace(fileMonitorPath, "")
                        .replace(file.getName(), "").replace("\\", "/");
                for (FtpConfig ftpConfig : ftpConfigs) {
                    pushFtp(ftpConfig, needMkdir, file);
                }
            }
        };
        observer.addListener(ftpFileAlterationListener);
        monitor.start();
    }

    /**
     * 推送文件至ftp服务器
     *
     * @param ftpConfig {@link FtpConfig}  ftp的配置
     * @param needMkdir {@link String}   需要创建的目录
     * @param file      {@link java.io.File} 需要推送到ftp的文件
     * @author hongsw
     * @date 2021/10/13 16:17
     **/
    private void pushFtp(FtpConfig ftpConfig, String needMkdir, File file) throws IOException {
        FTPClient ftpClient = new FTPClient();
        if (WINDOWS_OS.equalsIgnoreCase(ftpConfig.getOs())) {
            ftpClient.setControlEncoding("GBK");
        } else if (LINUX_OS.equalsIgnoreCase(ftpConfig.getOs())) {
            ftpClient.setControlEncoding("UTF-8");
        } else {
            log.error("暂不支持{}系统的FTP服务器", ftpConfig.getOs());
            return;
        }
        ftpClient.connect(ftpConfig.getIp());
        if (!ftpClient.login(ftpConfig.getUsername(), ftpConfig.getPassword())) {
            log.error("ip:{}", ftpConfig.getIp());
            log.error("username:{},password:{}", ftpConfig.getUsername(), ftpConfig.getPassword());
            log.error("登录ftp服务器失败");
            ftpClient.disconnect();
            return;
        }
        mkDirs(ftpClient, ftpConfig.getInitialPath() + needMkdir);
        log.info("当前工作路径：{}", ftpClient.printWorkingDirectory());
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        @Cleanup FileInputStream fileInputStream = new FileInputStream(file);
        if (!ftpClient.storeFile(file.getName(), fileInputStream)) {
            log.error("文件：{}，推送失败", file.getName());
        } else {
            log.info("推送文件为【{}】,ip为【{}】的Ftp服务器文件推送完毕", file.getName(), ftpConfig.getIp());
        }
        //  退出登录
        ftpClient.logout();
        // 断开连接
        ftpClient.disconnect();
    }


    /**
     * 创建多级目录
     *
     * @param client    {@link FTPClient} ftp端
     * @param directory {@link java.lang.String} 目录
     * @author hongsw
     * @date 2021/10/13 16:16
     **/
    private void mkDirs(FTPClient client, String directory) throws IOException {
        List<String> catalogs = Arrays.stream(directory.split("/"))
                .filter(i -> !"".equals(i))
                .collect(Collectors.toList());
        StringBuilder currentPath = new StringBuilder("/");
        for (String catalog : catalogs) {
            String temporaryPath = currentPath.append(catalog).toString();
            if (!client.changeWorkingDirectory(temporaryPath)) {
                client.makeDirectory(catalog);
                log.info("当前路径：{},创建文件夹:{}", temporaryPath, catalog);
                client.changeWorkingDirectory(temporaryPath);
            }
            currentPath.append("/");
        }
    }

}
